package com.ow.dva.module.order.app;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import com.ow.dva.config.ShopInfo;
import com.ow.dva.config.WXSCPayConfig;
import com.ow.dva.module.base.entity.json.RT;
import com.ow.dva.module.base.service.ImageService;
import com.ow.dva.module.base.service.KafkaService;
import com.ow.dva.module.order.entity.Order;
import com.ow.dva.module.order.service.OrderService;
import com.ow.dva.module.park.entity.Park;
import com.ow.dva.module.park.entity.Road;
import com.ow.dva.module.park.service.ParkService;
import com.ow.dva.module.park.service.RoadService;
import com.ow.dva.module.passingRecord.entity.PassingRecord;
import com.ow.dva.module.passingRecord.service.PassingRecordService;
import com.ow.dva.module.serverSettings.service.ServerSettingsService;
import com.ow.dva.util.DateOfMonth;
import com.ow.dva.util.QRCode.ZXingBackGroundUtils;
import com.ow.dva.util.UUIDFactory;
import com.ow.dva.util.pay.wxpay.HttpUtil;
import com.ow.dva.util.pay.wxpay.PayCommonUtil;
import com.ow.dva.util.pay.wxpay.RequestHandler;
import com.ow.dva.util.pay.wxpay.XMLUtil;
import org.jdom.JDOMException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;

@Controller
@RequestMapping("/app/order")
public class AppOrderController {

    @Resource
    private OrderService orderService;
    @Resource
    private RoadService roadService;
    @Resource
    private ParkService parkService;
    @Resource
    private PassingRecordService passingRecordService;
    @Resource
    private KafkaService kafkaService;
    @Resource
    private ServerSettingsService serverSettingsService;

    @Value("${dva.static-path}")
    private String staticPath;

    @Resource
    private ImageService imageService;

    private static ImageService staticImageService;

    @PostConstruct
    public void init(){
        staticImageService = imageService;
    }

    /**
     * 轮询该方法 根据车道id获取最新订单
     * @param roadId
     * @return
     */
    @RequestMapping(value = "/getNewOrder", method = RequestMethod.GET)
    @ResponseBody
    public RT getNewOrder(String roadId){
        Order order = orderService.selectNewOrderByRoad(roadId);
        if (order.getEnterRecordId()!=null){
            PassingRecord inner = passingRecordService.getById(order.getEnterRecordId());
            if (inner !=null){
                order.setInnerTime(inner.getPassTime());
            }
        }
        if (order.getLeaveRecordId()!=null){
            PassingRecord enter = passingRecordService.getById(order.getLeaveRecordId());
            if (enter !=null){
                order.setEnterTime(enter.getPassTime());
            }
        }
        if (order!=null){
            return RT.ok(order);
        }else {
            return RT.error(1,"暂无新订单！");
        }
    }

    /**
     * 获取微信和支付宝 支付二维码
     * @param orderId
     * @return
     */
    @RequestMapping(value = "/getWXPayCode", method = RequestMethod.GET)
    @ResponseBody
    public RT getWXPayCode(String orderId){
        String staticPath = "";
        String relativePath = "";
        staticPath = staticImageService.getStaticPath("/wx-pay-code");
        relativePath = staticImageService.generateImageFileName(staticPath,"image/jpeg");

//        String codeUrl = WXSCPayConfig.URL + "/app/order/confirmOrder?id="+orderId;
        String codeUrl = WXSCPayConfig.URL + "/app/order/isWxOrAli?id="+orderId;
        boolean b =ZXingBackGroundUtils.drawLogoQRCode(staticPath+"/src/main/resources/static/images/rt.jpg",staticPath+relativePath,codeUrl);
        if(b){
            RT rt = RT.ok();
            rt.setData("/wx-pay-code"+relativePath);
            return rt;
        }else{
            return RT.error(2,"微信支付二维码生成失败");
        }
    }

    /**
     * 模糊匹配过车记录
     * @param plate
     * @return
     */
    @RequestMapping("/matchPassRecord")
    @ResponseBody
    public RT matchPassRecord(String plate,String roadId){
        Road road = roadService.getById(roadId);

        List<PassingRecord> passingRecords = passingRecordService.matchPassRecord(plate,road.getParkId());
        if (passingRecords!=null && passingRecords.size()!=0){
            return RT.ok("找到以下记录！",passingRecords);
        }else {
            return RT.error(1,"未找到匹配的记录！");
        }
    }

    /**
     *
     * @param passRecordId
     * @return
     */
    @RequestMapping("/getMatchOrder")
    @ResponseBody
    public RT getMatchOrder(String passRecordId,String roadId) throws InterruptedException {
        PassingRecord passingRecord = passingRecordService.getById(passRecordId);
        Park park = parkService.getById(passingRecord.getParkId());
        String topic = park.getTerminaId();
        String orderId = UUIDFactory.getStringId();
        Map map = new HashMap();
        map.put("passRecordId",passRecordId);
        map.put("orderId",orderId);
        map.put("roadId",roadId);
        kafkaService.sendMessage(12,topic,map);
//        Thread.sleep(500);
        return RT.ok("正在向终端请求订单！",orderId);
    }
    /**
     *
     * @param id
     * @return
     */
    @RequestMapping(value = "/confirmOrder", method = RequestMethod.GET)
    public String wxLogin(String id) {
        System.out.println("---------------------------网页授权-----------------------");
        String backUrl= WXSCPayConfig.URL+"/app/order/Back?id="+id;
        String url ="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+ WXSCPayConfig.APPID
                + "&redirect_uri="+ URLEncoder.encode(backUrl)
                + "&response_type=code"
                + "&scope=snsapi_base"
                + "&state=STATE#wechat_redirect";
        return url;
    }

    @RequestMapping("/Back")
    public  String  Back(HttpServletRequest req, String id, HttpServletResponse res, ModelMap modelMap) {
        System.out.println("---------------------------回调中-----------------------");
        String openid =getOpenid(req);
        System.out.println("---------------------------openId:"+openid+"-----------------------");
        if(openid!=null && !"".equals(openid)){
            Order order = orderService.getById(id);
            if(order !=null){
                try {
                    uniformOrder(req,res,order,openid,modelMap);
                } catch (JDOMException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (order.getEnterRecordId()!=null){
                PassingRecord inner = passingRecordService.getById(order.getEnterRecordId());
                if (inner !=null){
                    order.setInnerTime(inner.getPassTime());
                }
            }
            if (order.getLeaveRecordId()!=null){
                PassingRecord enter = passingRecordService.getById(order.getLeaveRecordId());
                if (enter !=null){
                    order.setEnterTime(enter.getPassTime());
                }
            }
            modelMap.put("order",order);
        }
        return  "/pay/road_index";
    }
    /**
     *
     *
     * 扫描统一下单
     * @param request
     * @param response
     * @return
     * @throws JDOMException
     * @throws IOException
     */
    public void uniformOrder(HttpServletRequest request, HttpServletResponse response, Order order, String openId, ModelMap modelMap) throws JDOMException, IOException {
        System.out.println("--------------------扫描支付统一下单中(车道支付)-------------------------");
        String nonce_str = UUID.randomUUID().toString().replaceAll("-", "");
        //订单生成的机器 IP
        String spbill_create_ip = request.getRemoteAddr(); //获取客户端的真是的IP
        // 订单号
        String out_trade_no = order.getId();
        Integer total_fee =1; //费用
//        Integer total_fee = (int)(order.getReallyMoney()*100);//TODO 总金额
        String body ="微信车道支付";
        //这里notify_url是 支付完成后微信发给该链接信息，可以判断会员是否支付成功，改变订单状态等。
        SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
        packageParams.put("appid", WXSCPayConfig.APPID);
        packageParams.put("mch_id", WXSCPayConfig.MCHID);
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("body", body);
        packageParams.put("out_trade_no", out_trade_no);
        packageParams.put("total_fee", total_fee+"");
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("notify_url",WXSCPayConfig.CALLBACK_URL);
        packageParams.put("trade_type", "JSAPI");
        packageParams.put("openid", openId);
        System.out.println("回调路径"+WXSCPayConfig.CALLBACK_URL);
        //请求签名
        String sign = PayCommonUtil.createSign(WXSCPayConfig.CHARACTER, packageParams,WXSCPayConfig.WX_KEY);
        packageParams.put("sign", sign);
        //转换为xml格式的请求串
        String requestXML = PayCommonUtil.getRequestXml(packageParams);
//        //发送请求
        String resXml = HttpUtil.postData(WXSCPayConfig.MCH_URL, requestXML);
//        //返回内容转换为map
        Map map = XMLUtil.doXMLParse(resXml);
        String resultCode = (String) map.get("return_code");
        String prepay_id = (String) map.get("prepay_id");
        System.out.println("获取到的预支付ID："+ prepay_id);
        if("SUCCESS".equals(resultCode)){
            SortedMap<Object, Object> finalpackage = new TreeMap<Object, Object>();
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);;
            finalpackage.put("appId",map.get("appid"));//公众号id
            finalpackage.put("nonceStr",map.get("nonce_str")); // 支付签名随机串，不长于 32 位
            finalpackage.put("package","prepay_id=" + map.get("prepay_id")); // 支付签名随机串，不长于 32 位
            finalpackage.put("signType","MD5");
            finalpackage.put("timeStamp",timestamp);
            RequestHandler reqHandler = new RequestHandler(request, response);
            reqHandler.init(WXSCPayConfig.APPID,WXSCPayConfig.APPSECRET,WXSCPayConfig.WX_KEY);
            String finalsign = reqHandler.createSign(finalpackage);
            modelMap.put("appId",map.get("appid"));////公众号id
            modelMap.put("timeStamp", timestamp);//时间戳
            modelMap.put("nonceStr", map.get("nonce_str"));//随机字符串
            modelMap.put("packageValue","prepay_id=" + map.get("prepay_id"));//订单详情扩展字符串
            modelMap.put("paySign", finalsign);
        }
    }
    /**
     * 微信登录认证后的回调
     * @return
     */
    public  String  getOpenid(HttpServletRequest req){
        //start 获取微信用户基本信息
        String code =req.getParameter("code");
        String str="https://api.weixin.qq.com/sns/oauth2/access_token";
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("appid", WXSCPayConfig.APPID);
        paramMap.put("secret", WXSCPayConfig.APPSECRET);
        paramMap.put("code", code);
        paramMap.put("grant_type", "authorization_code");
        String result= cn.hutool.http.HttpUtil.post(str, paramMap);
        try {
            Gson gson = new Gson();
            Map<String, Object> res   = gson.fromJson(result, new TypeToken<Map<String, Object>>() {}.getType());
            String openid=(String) res.get("openid");
            return  openid;
        } catch (JsonSyntaxException e) {
            e.printStackTrace();
            return  "";
        }
    }

    /**
     * 手动输入金额支付
     * @param money
     * @param roadId
     * @return
     */
    @RequestMapping("/customOrder")
    @ResponseBody
    public RT customOrder(double money,String roadId){
        Road road = roadService.getById(roadId);
        String orderId = UUIDFactory.getRandomString();
        Order order = new Order(orderId,UUIDFactory.getRandomString(),road.getParkId(),road.getParkName(),"自定义收款",null,null,null,
                money,money,"手动输入金额收款",0,0,new Date());
        order.setRoadId(roadId);
        order.setjPushStatus(1);
        boolean res = orderService.save(order);
        if (res){
            String staticPath = "";
            String relativePath = "";
            staticPath = staticImageService.getStaticPath("/wx-pay-code");
            relativePath = staticImageService.generateImageFileName(staticPath,"image/jpeg");

            String codeUrl = WXSCPayConfig.URL + "/app/order/isWxOrAli?id="+orderId;

            boolean b =ZXingBackGroundUtils.drawLogoQRCode(staticPath+"/src/main/resources/static/images/rt.jpg",staticPath+relativePath,codeUrl);
            if(b){
                RT rt = RT.ok();
                rt.setData("/wx-pay-code"+relativePath);
                return rt;
            }else{
                return RT.error(2,"微信支付二维码生成失败");
            }
        }else {
            return RT.error(2,"微信支付二维码生成失败");
        }

    }

    @RequestMapping("/getOrderList")
    @ResponseBody
    public RT getOrderList(String roadId){
        List<Order> orders = orderService.selectOrderListByRoad(roadId);
        List<Order> orderList = new ArrayList<>();
        if (orders!=null && orders.size() != 0){
            for (Order order : orders){
                if (order.getEnterRecordId()!=null){
                    PassingRecord inner = passingRecordService.getById(order.getEnterRecordId());
                    if (inner !=null){
                        order.setInnerTime(inner.getPassTime());
                    }
                }
                if (order.getLeaveRecordId()!=null){
                    PassingRecord enter = passingRecordService.getById(order.getLeaveRecordId());
                    if (enter !=null){
                        order.setEnterTime(enter.getPassTime());
                    }
                }
                orderList.add(order);
            }
        }
        return RT.ok("查询成功",orderList);
    }


    @RequestMapping("/isWxOrAli")
    public String isWxOrAli(String id, HttpServletRequest request){
        RT rt = orderService.isWxOrAli(request);
        if (rt.getMessage().equals("1") ){
            try {
                String aliUrl = orderService.uniformOrder(id);
                return "redirect:"+aliUrl;
            } catch (AlipayApiException e) {
                e.printStackTrace();
            }
            return "下单失败";
        }else if (rt.getMessage().equals("2")){
            String url = wxLogin(id);
            return "redirect:"+url;///必须重定向，否则不能成功
        }else {
            return "未知来源";
        }

    }




    /**
     * <pre>
     * 第一步:验证签名,签名通过后进行第二步
     * 第二步:按一下步骤进行验证
     * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
     * 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
     * 3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
     * 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过，则表明本次通知是异常通知，务必忽略。
     * 在上述验证通过后商户必须根据支付宝不同类型的业务通知，正确的进行不同的业务处理，并且过滤重复的通知结果数据。
     * 在支付宝的业务通知中，只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时，支付宝才会认定为买家付款成功。
     * </pre>
     *
     * @param
     * @return
     */
    @RequestMapping("/aliAppcallback")
    @ResponseBody
    public String callback(HttpServletRequest request) {
        System.out.println("--------------支付宝支付回调----------------");
        Map<String, String> params = convertRequestParamsToMap(request); // 将异步通知中收到的待验证所有参数都存放到map中
        String paramsJson = JSON.toJSONString(params);
        try {
//            AlipayConfig alipayConfig = new AlipayConfig();// 支付宝配置
            // 调用SDK验证签名
            boolean signVerified = AlipaySignature.rsaCheckV1(params, ShopInfo.ALIPAYPUBLICKEY,
                    ShopInfo.CHARSET, ShopInfo.signType);
            if (signVerified) {
                System.out.println("支付宝回调签名认证成功");
                String outTradeNo = params.get("out_trade_no");
                Order order = orderService.getById(outTradeNo);
                if(order == null){
                    System.out.println("订单数据异常！订单不存在！");
                    return "failure";
                }
                order.setPayType(1);
                order.setOrderStatus(1);
                orderService.updateById(order);

                //订单支付成功推送消息
                try {
                    orderService.jpush(order,"2");
                }catch (Exception e){
                    e.printStackTrace();
                    System.out.println("推送消息异常！！");
                }
                return "success";
            } else {
                System.out.println("支付宝回调签名认证失败，signVerified=false, paramsJson:{}"+paramsJson);
                return "failure";
            }
        } catch (AlipayApiException e) {
            System.out.println("支付宝回调签名认证失败,paramsJson:{},errorMsg:{}"+ paramsJson+"----------"+ e.getMessage());
            return "failure";
        }
    }


    // 将request中的参数转换成Map
    private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
        Map<String, String> retMap = new HashMap<String, String>();

        Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();

        for (Map.Entry<String, String[]> entry : entrySet) {
            String name = entry.getKey();
            String[] values = entry.getValue();
            int valLen = values.length;

            if (valLen == 1) {
                retMap.put(name, values[0]);
            } else if (valLen > 1) {
                StringBuilder sb = new StringBuilder();
                for (String val : values) {
                    sb.append(",").append(val);
                }
                retMap.put(name, sb.toString().substring(1));
            } else {
                retMap.put(name, "");
            }
        }

        return retMap;
    }

    /**
     * 微信付款页面轮询
     * @param orderId
     * @return
     */
    @RequestMapping(value = "/timerOrderCallBack")
    @ResponseBody
    public RT timerOrderCallBack(String orderId){
        Order order = orderService.getById(orderId);
        if (order!=null && order.getId()!=null){
            if (order.getOrderStatus()==1){
                return RT.ok();
            }else {
                return RT.error(1);
            }
        }else {
            return RT.error(1);
        }
    }

    /**
     * 跳转支付成功页面
     * @return
     */
    @RequestMapping(value = "/pay_success")
    public String pay_success(){
        return "/pay/pay_success";
    }

}
